package common.extractText;

import cn.hutool.core.util.NumberUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class References {

    //    static String tableName = "pdf.pmid_pdf_sentence"; // 保存的表名
    static String connector = "ㅠ⫅ㅛ".toLowerCase(); // 连接符-
    static String paragraph = "ㅑ╉╧".toLowerCase(); // 段落开始符
    static String subProject = "ㅠ⨦ⱔ".toLowerCase(); // 子段落开始符
    static String lineBreak = "⬆เ⎨".toLowerCase(); // 换行符号，文本加入保存时，前面均要加上这个符号
    static String lastStr = "∱≱⬇".toLowerCase(); // 整个文档的结束符号

    public static String doReferences(String references, String paragraph, String lineBreak, String lastStr, Set<String> pOrder, String paragraph_name, List<Integer> sOrder, String subProject_Name, List<Change.TableField> tableList) {
        String[] resultList = references.split(lineBreak);
        String type = referencesType(references, paragraph, lineBreak, lastStr);
//        System.out.println("type: 1 " + type);
        if (type.equals("doi")) { // 参文中含有doi居多的
            String str = references.replaceAll(" +", " ").replaceAll(" ([0-9])", "$1").replace(" .", ".").replace(" /", "/").replace("/ ", "/");
            if (str.indexOf(". doi:") > 0) {
                String[] split = str.split("doi:");
                for (String s : split) {
                    String f = "";
                    int index = str.indexOf(". doi:");
                    if (index > 0) {
                        String http = str.substring(index + 2);
                        String[] list = http.split("");
                        for (int i = 0; i < list.length; i++) {
                            String substring = http.substring(i);
                            if (Pattern.compile("^ ⬆เ⎨[A-Z]").matcher(substring).find()) {
                                if (str.length() > index + 2 + i + 2) {
                                    f = str.substring(0, index + 2 + i);
                                    str = str.substring(index + 2 + i + 1);
                                    Tools.insertTable(pOrder, paragraph_name, sOrder, f.replace(lineBreak, ""), subProject_Name, 1, tableList);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            Tools.insertTable(pOrder, paragraph_name, sOrder, str.replace(lineBreak, ""), subProject_Name, 1, tableList);
        }

        if (type.equals("c")) { // 这种是序号在一行，参文另起一行，或者参文也在同一行的，都是一个方法，但此方法需要对序号作限制，只要1-3位，因为发现了许多"2022. "这种四位的。
            StringBuilder sStr = new StringBuilder();
            resultList = dellBlankSpace(resultList); // 如果参文中，每一行下面是一空行，则给予删除
            for (int i = 0; i < resultList.length; i++) {
                String str = resultList[i];
                String s = str.trim();
                String next = (resultList.length > i + 1) ? resultList[i + 1].trim() : "";
//                System.out.println("str:1 " + str + " next: " + next);
                if ((Pattern.compile("^[0-9]{1,3}\\.$").matcher(s).find() && Pattern.compile("^[A-Z][a-z]").matcher(next).find()) ||
                        (Pattern.compile("^[0-9]{1,3}$").matcher(s).find() && Pattern.compile("^[A-Z][a-z]").matcher(next).find()) ||
                        (Pattern.compile("^[0-9]{1,3}\\. [A-Z]").matcher(s).find() && !Pattern.compile("^[0-9]{1,3}\\. PMID").matcher(s).find())) {
                    sStr.append(subProject); // 在这里只是把subProject当作了切割符，下面有用到。
//                    System.out.println("str:2 " + str + " next: " + next);
                }
                sStr.append(str).append(" ");
            }
            String[] list = sStr.toString().split(subProject);
            for (String s : list) {
                Tools.insertTable(pOrder, paragraph_name, sOrder, s.replace(lineBreak, ""), subProject_Name, 10, tableList);
            }
        }

        if (type.equals("g")) { // 这种是序号被方括号在括住的
            StringBuilder sStr = new StringBuilder();
            for (int i = 0; i < resultList.length; i++) {
                String str = resultList[i];
                String s = str.trim();
                String next = (resultList.length > i + 1) ? resultList[i + 1].trim() : "";
                if ((Pattern.compile("^\\[[0-9]{1,3}\\]$").matcher(s).find() && Pattern.compile("^[A-Z]").matcher(next).find()) || (Pattern.compile("^\\[[0-9]+\\] [A-Z]").matcher(s).find() && !Pattern.compile("^\\[[0-9]+\\] PMID").matcher(s).find())) {
                    sStr.append(subProject);
                }
                sStr.append(str).append(" ");
            }
            String[] list = sStr.toString().split(subProject);
            for (String s : list) {
                Tools.insertTable(pOrder, paragraph_name, sOrder, s.replace(lineBreak, ""), subProject_Name, 10, tableList);
            }
        }

        if (type.equals("k")) { // 这种是序号被方括号在括住的
            StringBuilder sStr = new StringBuilder();
            for (int i = 0; i < resultList.length; i++) {
                String str = resultList[i];
                String s = str.trim();
                String next = (resultList.length > i + 1) ? resultList[i + 1].trim() : "";
                if ((Pattern.compile("^\\([0-9]{1,3}\\)$").matcher(s).find() && Pattern.compile("^[A-Z]").matcher(next).find()) || (Pattern.compile("^\\([0-9]+\\) [A-Z]").matcher(s).find() && !Pattern.compile("^\\([0-9]+\\) PMID").matcher(s).find())) {
                    sStr.append(subProject);
                }
                sStr.append(str).append(" ");
            }
            String[] list = sStr.toString().split(subProject);
            for (String s : list) {
                Tools.insertTable(pOrder, paragraph_name, sOrder, s.replace(lineBreak, ""), subProject_Name, 10, tableList);
            }
        }

        if (type.equals("j")) { // 这种是没有序号的，规则是每一行的参文以句号结尾，下一行为空，之后才开始新的一行。
            String str = references.replaceAll(" +", " ").replaceAll(" ([0-9])", "$1").replace(" .", ".").replace(" /", "/").replace("/ ", "/");
            List<String> saveList = new ArrayList<>();
            Change.doMatcher(str, "\\. ⬆เ⎨ ⬆เ⎨[A-Z][a-z]", 9, 2, saveList);
            for (String s : saveList) {
                Tools.insertTable(pOrder, paragraph_name, sOrder, s.replace(lineBreak, ""), subProject_Name, 10, tableList);
            }
        }

        if (type.equals("http")) {
            String str = references.replaceAll(" +", " ").replaceAll(" ([0-9])", "$1").replace(" .", ".").replace(" /", "/").replace("/ ", "/");
//            System.out.println("--str: " + str);
            if (str.indexOf(". http") > 0) {
                String[] split = str.split("http");
                for (String s : split) {
                    String f = "";
                    int index = str.indexOf(". http");
                    if (index > 0) {
                        String http = str.substring(index + 2);
//                        System.out.println("--http: " + http);
                        String[] list = http.split("");
                        for (int i = 0; i < list.length; i++) {
                            String substring = http.substring(i);
                            if (Pattern.compile("^\\. ⬆เ⎨[A-Z][a-z]").matcher(substring).find()) {
                                if (str.length() > index + 2 + i + 2) {
                                    f = str.substring(0, index + 2 + i + 2);
                                    str = str.substring(index + 2 + i + 2);
                                    Tools.insertTable(pOrder, paragraph_name, sOrder, f.replace(lineBreak, ""), subProject_Name, 10, tableList);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            Tools.insertTable(pOrder, paragraph_name, sOrder, str.replace(lineBreak, ""), subProject_Name, 10, tableList);
        }

        StringBuilder sStr = new StringBuilder();
        for (int j = 0; j < resultList.length; j++) {
            String str = resultList[j];
            String r = sStr.toString();
            String next = (resultList.length > j + 1) ? resultList[j + 1].trim() : "";

            if (type.equals("Other")) {
                sStr.append(str).append(" ");
//                Tools.insertTable(tableName, pOrder, paragraph_name, sOrder, file_id, str.replace(lineBreak, ""), subProject_Name, 10);
            }

            if (type.equals("a")) {
                if ((Pattern.compile("[A-Z]\\., and [A-Z]").matcher(r).find() || Pattern.compile("[A-Z]\\. and [A-Z]").matcher(r).find() || r.toLowerCase().contains("https://") || r.toLowerCase().contains("http://")) && Pattern.compile("[A-Z]\\.: [A-Z]").matcher(r).find() &&
                        (r.trim().endsWith(".") || r.toLowerCase().contains("https://") || r.toLowerCase().contains("http://")) && (Pattern.compile("[A-Z]\\., and [A-Z]").matcher(str).find() ||
                        Pattern.compile("[A-Z]\\. and [A-Z]").matcher(str).find() || Pattern.compile("[A-Z]\\.: [A-Z]").matcher(str).find() || Pattern.compile("[A-Z]\\., [A-Z]").matcher(str).find())) {
                    Tools.insertTable(pOrder, paragraph_name, sOrder, sStr.toString().replace(lineBreak, ""), subProject_Name, 10, tableList);
                    sStr = new StringBuilder();
                    sStr.append(str).append(" ");
                } else {
                    sStr.append(str).append(" ");
                    continue;
                }
            }
            if (type.equals("f")) {
                String s = sStr.toString();
                Matcher matcher = Pattern.compile("[0-9] [0-9]{1,3} [A-Z][a-z]").matcher(s);
                if (matcher.find()) {
                    String f = s.substring(0, s.indexOf(matcher.group(0)) + 1);
                    String e = s.substring(s.indexOf(matcher.group(0)) + 2);
//                    System.out.println("--f: " + f);
                    Tools.insertTable(pOrder, paragraph_name, sOrder, f.replace(lineBreak, ""), subProject_Name, 10, tableList);
                    sStr = new StringBuilder();
                    sStr.append(e).append(" ");
                }
                String t = sStr.toString().trim();
                if (((NumberUtil.isInteger(str.trim()) && str.trim().length() < 4) || Pattern.compile("^[0-9]{1,3} [A-Z][a-z]").matcher(str.trim()).find())  // 要求序号的数字，长度不能超过3位，好最大为3位。
                        && !t.endsWith(":") && !t.endsWith("-") && !t.endsWith(",") && !t.endsWith(".")) {
//                    System.out.println("--sStr.toString(): " + sStr.toString());
                    Tools.insertTable(pOrder, paragraph_name, sOrder, sStr.toString().replace(lineBreak, ""), subProject_Name, 10, tableList);
                    sStr = new StringBuilder();
                }
                sStr.append(str).append(" ");
            }
        }
        Tools.insertTable(pOrder, paragraph_name, sOrder, sStr.toString().replace(lineBreak, ""), subProject_Name, 10, tableList);
        return type;
    }

    // 判断论文的参文类型。
    public static String referencesType(String references, String paragraph, String lineBreak, String lastStr) {
        int c = 0;
        int http = 0;
        int doi = 0;
        int f = 0;
        int g = 0;
        int h = 0;
        int j = 0;
        int k = 0;
        String[] split = references.split(lineBreak);
        int sum = split.length == 0 ? 1 : split.length;

        for (int i = 0; i < split.length; i++) {
            String str = split[i];
            String next = (split.length > i + 1) ? split[i + 1].trim() : "";
            String s = str.trim();
//            System.out.println("----s: " + s);

            if (s.endsWith(".") && next.length() < 1) { // 这种是没有序号的，规则是每一行的参文以句号结尾，下一行为空，之后才开始新的一行。
                j++;
            }
            if (j > 5 || (j > 3 && i == split.length - 1)) {
//                System.out.println("--g: " + g);
                return "j";
            }

            c = (Pattern.compile("^[0-9]{1,3}\\.$").matcher(s).find() || Pattern.compile("^[0-9]{1,3}$").matcher(s).find()) ? c + 1 : c; // 这种是序号在一行，参文另起一行，或者参文也在同一行的，都是一个方法
            if (c > 5 || (c > 3 && i == split.length - 1)) {
                return "c";
            }
//            System.out.println("--s: " + s);
            g = (Pattern.compile("^\\[[0-9]{1,3}\\]$").matcher(s).find() || Pattern.compile("^\\[[0-9]{1,3}\\] [A-Z]").matcher(s).find()) ? g + 1 : g; // 这种是序号被方括号在括住的
            if (g > 5 || (g > 3 && i == split.length - 1)) {
//                System.out.println("--g: " + g);
                return "g";
            }
            k = (Pattern.compile("^\\([0-9]{1,3}\\)$").matcher(s).find() || Pattern.compile("^\\([0-9]{1,3}\\) [A-Z]").matcher(s).find()) ? k + 1 : k; // 这种是序号被方括号在括住的
            if (k > 5 || (k > 3 && i == split.length - 1)) {
//                System.out.println("--g: " + g);
                return "k";
            }
            f = Pattern.compile("^[0-9]{1,3} [A-Z][a-z]").matcher(s).find() ? f + 1 : f; // 这种是序号和参文在一起的，且序号后面是空格，再后面是大写字母，再后面是小写字母。
            if (f > 5 || (f > 3 && i == split.length - 1)) {
                return "f";
            }
            h = Pattern.compile("^[0-9]{1,3}\\. [A-Z][a-z]").matcher(s).find() ? h + 1 : h; // 这种是序号和参文在一起的，且序号后面是空格，再后面是大写字母，再后面是小写字母。
            if (h > 4 || (h > 3 && i == split.length - 1)) { // 如果已经到了最后了，数量h只要大于3个，也是可以的。说明参文数量可能比较少。
                return "c";
            }
            // 这种是没有序号的类型的一种
            if ((Pattern.compile("[A-Z]\\., and [A-Z]").matcher(s).find() || Pattern.compile("[A-Z]\\. and [A-Z]").matcher(s).find() || s.toLowerCase().contains("https://") || s.toLowerCase().contains("http://")) &&
                    Pattern.compile("[A-Z]\\.: [A-Z]").matcher(s).find() && (s.endsWith(".") || s.toLowerCase().contains("https://") || s.toLowerCase().contains("http://"))) {
                return "a";
            }

            int length = s.split("\\. http").length; // 参文中含有网址居多的
            http = length > 1 ? http + length : http;
            int len = s.split("\\. doi: ").length; // 参文中含有doi居多的
            doi = len > 1 ? doi + len : doi;
            String t = s.replace(lineBreak, "");
            if (ReadTxt.isReferencesEnd(t, t)) {
                break;
            }
        }
        double div = Tools.Arith.div(http, sum);
//        System.out.println("div:1 " + div + " d: " + http + " sum: " + sum);
        if (div > 0.35) { // 如果按三行为一条参文记录的话，大于0.35基本上每一条都有一条链接了。
            return "http";
        }
        div = Tools.Arith.div(doi, sum);
//        System.out.println("div:2 " + div + " e: " + doi + " sum: " + sum);
        if (div > 0.35) {
            return "doi";
        }
        return "Other";
    }

    // 空白行给予删除
    public static String[] dellBlankSpace(String[] split) {
        List<String> result = new ArrayList<>();
        for (String s : split) {
            if (s.trim().length() > 0) {
                result.add(s);
            }
        }
        return result.toArray(new String[0]);
    }


}
